package com.zhuangjie.rabbit.config.wrap;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.UUID;
@Component
@Slf4j
public class MQAutoConfig  {
    @Autowired(required = false)
    private List<MQStructureConfig> mqStructureConfigs;

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        //此处也设置为手动ack
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        return factory;
    }

    /**
     * 自动配置mq的交换机、队列、绑定关系
     */
    @PostConstruct
    public void autoConfigMQ() {
        log.info("MQ“交换机、队列、绑定关系”自动配置中...");
        if (mqStructureConfigs == null ) return;
        for (MQStructureConfig mqStructureConfig : mqStructureConfigs) {
            List<ExchangeWrap> exchangeWraps = mqStructureConfig.exchangeWrap();
            exchangeWraps.stream().forEach(this::registerExchange);
        }
    }

    private String genQueueBeanName() {
        return "Queue:"+ UUID.randomUUID();
    }

    private String genExchangeBeanName() {
        return "Exchange:"+ UUID.randomUUID();
    }
    private String genBindingBeanName() {
        return "Binding:"+ UUID.randomUUID();
    }
    private void registerBean(String beanName,Object bean) {
        // 将实例手动注册到IOC容器中
        ConfigurableListableBeanFactory beanFactory =
                ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
        beanFactory.registerSingleton(beanName, bean);
    }
    private void registerExchange(ExchangeWrap exchangeWrap) {
        // 将当前注册路由的方法注入到ExchangeWrap中
        if (exchangeWrap.getExchangeRegisterRequest() != null) exchangeWrap.getExchangeRegisterRequest().accept(this::registerExchange);
        // 注册当前的交换机
        Exchange exchange = exchangeWrap.getExchange();
        registerBean(genExchangeBeanName(),exchange);
        List<ExchangeWrap.QueueWrap> queueWraps = exchangeWrap.getQueueWraps();
        if (queueWraps == null ) return;
        for (ExchangeWrap.QueueWrap queueWrap : queueWraps) {
            Queue queue = queueWrap.getQueue();
            registerBean(genQueueBeanName(),queue);
            String routeKey = queueWrap.getRouteKey();
            Binding binding = BindingBuilder.bind(queue).to(exchange).with(routeKey).noargs();
            registerBean(genBindingBeanName(),binding);
        }
    }
}
